package com.zhang.yunfu_norevocation.comm.Utils;

import com.alibaba.fastjson.JSON;
import com.ccsp.sdk.crypto.CryptoException;
import com.sansec.util.encoders.Base64;
import com.zhang.yunfu_norevocation.entity.dto.InquiryPrescriptionDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;

import static com.zhang.comm.constant.Constant.P7_TAG;

/**
 * @author zsj
 * @description
 * @createDate 2025/11/6 12:59
 * @Entity com.dxih.inquiry.util.entity.
 */
@Slf4j
public class NoRevocationUtils {


    // 不可否认性校验
    public static boolean checkNotDeniable(InquiryPrescriptionDO entity) throws CryptoException {
        KingNetUtils kingNetUtils = new KingNetUtils();

        if (entity == null || entity.getNoRevocationStatus() != 1 || StringUtils.isAnyBlank(entity.getP7Signature(), entity.getSm3Hash(), entity.getTimestampToken())) {
            log.error("【不可否认性CHECK】参数错误，处方编号：{}", entity.getPrescriptNo());
            return false;
        }
        // 1. 拼接原始数据
        String oriData = buildOriData(entity);
        // 2. 校验P7签名
        boolean v7Flag = KingNetUtils.P7Verify(oriData.getBytes());
        if (!v7Flag){
            log.error("【不可否认性CHECK】p7验签失败，处方编号为：{}", entity.getPrescriptNo());
            return false;
        }

        // 3. 校验SM3哈希（重新计算并比对）
        byte[] currentSm3 = kingNetUtils.getSM3Bytes(oriData);
        String currentSm3Hash = Base64.toBase64String(currentSm3);
        if (!currentSm3Hash.equals(entity.getSm3Hash())) {
            log.error("【不可否认性CHECK】SM3校验失败，处方编号：{}", entity.getPrescriptNo());
            return false;
        }

        // 校验时间戳令牌
        String verifyResult = KingNetUtils.VerifyTimeStampToken(oriData+entity.getSm3Hash(), entity.getTimestampToken());
        int status = JSON.parseObject(verifyResult).getInteger("status");
        if (status != 0) {
            log.error("【不可否认性CHECK】时间戳校验失败，处方编号：{}", entity.getPrescriptNo());
            return false;
        }

        return true;
    }

    // 不可否认性添加
    public static boolean addNotDeniable(InquiryPrescriptionDO entity) throws CryptoException, IOException {
        KingNetUtils kingNetUtils = new KingNetUtils();
        if (entity.getNoRevocationStatus() == 1){
            log.error("【不可否认性ADD】重复添加，处方编号：{}", entity.getPrescriptNo());
            return false;
        }
        if (entity == null || StringUtils.isAllBlank(entity.getPrescriptNo(), entity.getIssuingTime().toString(), entity.getPrescriptionType(), entity.getPrescriptStatus(), entity.getAmount().toString())) {
            log.error("【不可否认性ADD】参数错误，处方编号：{}", entity.getPrescriptNo());
            return false;
        }

        // p7签名
        String oriData = buildOriData(entity);
        byte[] p7Sign = KingNetUtils.P7Sign(P7_TAG, "cert/【签名证书】0001_SM2_signcert.cer", oriData.getBytes());
        if (p7Sign == null || p7Sign.length == 0) {
            log.error("【不可否认性ADD】p7签名失败，处方编号：{}", entity.getPrescriptNo());
            return false;
        }
        // 生成SM3哈希
        byte[] sm3Bytes = kingNetUtils.getSM3Bytes(oriData);
        String sm3Hash = Base64.toBase64String(sm3Bytes);
        if (StringUtils.isBlank(sm3Hash)) {
            log.error("【不可否认性ADD】生成SM3哈希失败，处方编号：{}", entity.getPrescriptNo());
            return false;  // 生成失败
        }

        // 获取时间戳令牌（原始数据 + sm3Hash）
        String timeStampToken = KingNetUtils.GetTimeStampToken2Base64(oriData + sm3Hash);
        if (StringUtils.isBlank(timeStampToken)) {
            log.error("【不可否认性ADD】获取时间戳失败，处方编号：{}", entity.getPrescriptNo());
            return false;
        }

        // 5. 赋值给实体类
        entity.setP7Signature(Base64.toBase64String(p7Sign));  // P7签名需Base64存储
        entity.setTimestampToken(timeStampToken);
        entity.setSm3Hash(sm3Hash);
        entity.setNoRevocationStatus(1); // 1: 成功

        return true;
    }

    // 拼接字段
    public static String buildOriData(InquiryPrescriptionDO entity) {
        StringBuilder sb = new StringBuilder();
        // 处方编号
        sb.append(entity.getPrescriptNo() == null ? "" : entity.getPrescriptNo());
        // 开方时间戳
        sb.append(entity.getIssuingTime() == null ? "" : entity.getIssuingTime().getTime());
        // 处方类型
        sb.append(entity.getPrescriptionType() == null ? "0" : entity.getPrescriptionType());
        // 处方状态
        sb.append(entity.getPrescriptStatus() == null ? "0" : entity.getPrescriptStatus());
        // 金额
        sb.append(entity.getAmount() == null ? "0.00" : entity.getAmount().toPlainString()); // 避免科学计数法


        // 开方医生个人标识（TODO：该字段？？选取）
        String doctorId = new String();
        //doctorId = entity.get???() == null ? "" : entity.get??();
        if (StringUtils.isBlank(doctorId)) {
            log.warn("【不可否认性】开方医生个人标识为空，处方编号：{}", entity.getPrescriptNo());
            // throw new IllegalArgumentException("开方医生个人标识不能为空，处方编号：" + entity.getPrescriptNo());
        }
        sb.append(doctorId);
        return sb.toString();
    }
}
